<?php

namespace app\merchant\model;

use app\common\model\Order as OrderModel;
use app\store\model\OrderAddress as OrderAddressModel;
use app\store\model\User as UserModel;
use app\store\model\UserCoupon as UserCouponModel;
use app\store\service\order\Export as Exportservice;
use app\common\library\helper;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\service\Message as MessageService;
use app\common\service\order\Refund as RefundService;
use app\common\service\wechat\wow\Order as WowService;
use app\common\service\goods\source\Factory as FactoryStock;
use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\enum\order\Status as OrderStatusEnum;

/**
 * 订单管理
 * Class Order
 * @package app\store\model
 */
class Order extends OrderModel
{


    /**
     * 所有订单列表
     * @param string $dataType
     * @param array $query
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function getList($dataType, $query = [])
    {

        $wxapp_id = self::$wxapp_id;
        $filter = $this->getDataType($dataType);

        //普通订单
        $commonwhere = " common_order.is_delete=0  AND common_order.wxapp_id ={$wxapp_id}";
        $commonwhere .= $filter['commonfilter'];

        //爆品订单
        $giftswhere = " gifts_order.is_delete=0  AND gifts_order.wxapp_id ={$wxapp_id}";
        $giftswhere .= $filter['giftsfilter'];


        if (isset($query['search']) && !empty($query['search'])) {
            $commonwhere .= " AND (common_order.order_no LIKE '%" . $query['search'] . "%' OR user1.nickName LIKE '%" . $query['search'] . "%')";
            $giftswhere .= "  AND (gifts_order.order_no LIKE '%" . $query['search'] . "%' OR user2.nickName LIKE '%" . $query['search'] . "%')";

        }
        //付款状态  (10未付款 20已付款)
        if (isset($query['pay_status']) && $query['pay_status'] > 0) {
            $commonwhere .= " AND common_order.pay_status = {$query['pay_status']}";
            $giftswhere .= "  AND gifts_order.pay_status = {$query['pay_status']}";
        }
        //下单开始时间
        if (isset($query['starttime']) && !empty($query['starttime'])) {
            $commonwhere .= " AND common_order.create_time >=" .strtotime($query['starttime']);
            $giftswhere .= "  AND gifts_order.create_time >=" .strtotime($query['starttime']);
        }

        //下单结束时间
        if (isset($query['endtime']) && !empty($query['endtime'])) {

            $endtime = strtotime($query['starttime'])+86400;

            $commonwhere .= " AND common_order.create_time <=" .$endtime;
            $giftswhere .= "  AND gifts_order.create_time <=" .$endtime;
        }

        //订单来源 (5爆品订单 10商品订单 20砍价订单 30秒杀订单 40储值卡 50当面付)
        if (isset($query['order_source']) && !empty($query['order_source'])) {
            $commonwhere .= " AND common_order.order_source = {$query['order_source']}";
            $giftswhere .= "  AND gifts_order.order_source = {$query['order_source']}";
        }

        // 用户id
        if (isset($query['user_id']) && $query['user_id'] > 0) {
            $commonwhere .= " AND user1.user_id = {$query['user_id']}";
            $giftswhere .= "  AND user2.user_id = {$query['user_id']}";
        }


        $page = isset($query['page']) && is_numeric($query['page']) ? intval($query['page']) : 1;
        $limit = 15;
        $offset = ($page - 1) * $limit;

        //获取订单列表
        $db = db();

        $countSql = "
        (SELECT `order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`common_order`.`is_fictitious`,`user1`.`user_id`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,`gifts_order`.`order_source`,`gifts_order`.`create_time`,10 as `order_status`,1 as `is_fictitious`,`user2`.`user_id`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time`
        ";
        //总记录
        $count = count($db->query($countSql));

        $sql = "
        (SELECT `common_order`.`order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`user1`.`user_id`,`common_order`.`is_fictitious`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,5 as `order_source`,`gifts_order`.`create_time`,10 as `order_status`,`user2`.`user_id`,1 as `is_fictitious`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time` DESC LIMIT {$offset},{$limit}
        ";
        $listData = $db->query($sql);

        $list = $this->handleOrder($listData);

        //计算总页数
        $last_page = 0;

        $last_page = ceil( $count/15);

        $data = [
            'total' => $count,//总条数
            'per_page' => 15,//每页的条数
            'last_page' => $last_page,//总共多少页
            'data' => $list,//数据
        ];

        return $data;

    }



    /**
     * 处理数据
     * @param $value
     * @param $list
     * @return string
     */
    public function handleOrder($list)
    {
        $goods = [];

        //处理数据
        foreach($list as $k=>&$v){
            if($v['pay_status'] == 20){
                $v['order_status'] == 30;
            }
            //爆品礼订单
            if($v['order_source']==5){
                $goods = db('gifts_order_goods')
                    ->alias('a')
                    ->join('yoshop_upload_file b','a.image_id=b.file_id')
                    ->where(['a.order_id'=>$v['order_id']])
                    ->field('a.gifts_id as goods_id,a.gifts_title as goods_name,a.gifts_price as goods_price,1 as total_num,a.image_id,b.storage,b.file_url,b.file_name')
                    ->select()->toArray();

                foreach($goods as $kk=>&$vv){
                    $vv['image_url'] = $this->getFilePath($vv);
                }
                $v['goods'] = $goods;
            }
            //10普通订单 20砍价订单 30秒杀订单
            if($v['order_source']==10 || $v['order_source']==20 || $v['order_source']==30){
                $goods = db('order_goods')
                    ->alias('a')
                    ->join('yoshop_upload_file b','a.image_id=b.file_id')
                    ->where(['a.order_id'=>$v['order_id']])
                    ->field('a.goods_id,a.goods_name,a.goods_price,a.total_num,a.image_id,b.storage,b.file_url,b.file_name')
                    ->select()->toArray();
                foreach($goods as $kk=>&$vv){
                    $vv['image_url'] = $this->getFilePath($vv);
                }
                $v['goods'] = $goods;
            }
            //40购买会员订单
            if($v['order_source']==40){
                $goods = db('wxapp_card_order_plan')
                    ->alias('a')
                    ->join('yoshop_upload_file b','a.image_id=b.file_id')
                    ->where(['a.order_id'=>$v['order_id']])
                    ->field('a.card_id as goods_id,a.card_title as goods_name,a.card_real_money as goods_price,1 as total_num,a.image_id,b.storage,b.file_url,b.file_name')
                    ->select()->toArray();
                foreach($goods as $kk=>&$vv){
                    $vv['image_url'] = $this->getFilePath($vv);
                }
                $v['goods'] = $goods;
            }
            //50当面付订单
            if($v['order_source']==50){
                $goods = [
                    [
                        'goods_id' => 0,
                        'goods_name' => "当面付",
                        'goods_price'=>$v['pay_price'],
                        'total_num'=>1,
                        'image_url' => "",
                    ]
                ];

                $v['goods'] = $goods;
            }
            $v['create_time'] = date('Y-m-d H:i:s',$v['create_time']);
        }

        return $list;
    }



    /**
     * 获取图片完整路径
     * @param $value
     * @param $data
     * @return string
     */
    public function getFilePath($data)
    {
        if ($data['storage'] === 'local') {
            return self::$base_url . 'uploads/' . $data['file_name'];
        }
        return $data['file_url'] . '/' . $data['file_name'];
    }


    /**
     * 转义数据类型条件
     * @param $dataType
     * @return array
     */
    private function getDataType($dataType)
    {
        $commonfilter = "";
        $giftsfilter = "";

        switch ($dataType) {
            //待发货
            case 'delivery':
                $commonfilter .= " AND pay_status = 20  AND  delivery_status = 10 AND order_status IN (10,21)";
                $giftsfilter .= " AND pay_status = 30";
                break;
            //待收货
            case 'receipt':
                $commonfilter .= " AND pay_status = 20  AND  delivery_status = 20 AND order_status = 10";
                $giftsfilter .= " AND pay_status = 30";
                break;
            //待付款
            case 'pay':
                $commonfilter .= " AND pay_status = 10  AND  order_status = 10";
                $giftsfilter .= " AND pay_status = 10";
                break;
            //已完成
            case 'complete':
                $commonfilter .= " AND order_status = 30";
                $giftsfilter .= " AND pay_status = 30";
                break;
            //已取消
            case 'cancel':
                $commonfilter .= " AND order_status = 20";
                $giftsfilter .= " AND pay_status = 30";
                break;
            //全部订单
            case 'all':
                $commonfilter .= "";
                $giftsfilter .= "";
                break;
        }

        return ['commonfilter'=>$commonfilter,'giftsfilter'=>$giftsfilter];
    }




    /**
     * 全部订单导出
     * @param $dataType
     * @param $query
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function exportList($query)
    {
        //搜索条件
        $param = array_merge([
            'dataType' => "all", //all、全部订单  delivery、待发货  receipt、待收货  pay、待付款   complete、已完成  cancel_list、已取消
        ], $query);

        header("Content-type:text/html;charset=utf-8");
        $mpName = '订单';
        $limit = 500;//每次只从数据库取50000条以防变量缓存太大
        // buffer计数器
        $cnt = 0;
        set_time_limit(0);
        //计算总的数据
        $sqlCount = $this->getExportList($param,0, $limit,true);

        if($sqlCount<1){
            $this->error = '无数据导出';
            return false;
        }

        $xlsTitle = [
            '订单号', '商品信息', '买家', '实付款', '支付状态', '支付方式', '订单类型','下单时间'
        ];

        $fileName = $mpName . date('Y-m-d');// 文件名称可根据自己情况设定
        // 输出Excel文件头，可把user.csv换成你要的文件名
        header('Content-Type: application/vnd.ms-excel;charset=utf-8');
        header('Content-Disposition: attachment;filename="' . $fileName . '"');
        header('Cache-Control: max-age=0');


        $fileNameArr = array();
        // 逐行取出数据，不浪费内存
        for ($i = 0; $i < ceil($sqlCount / $limit); $i++) {

            $fp = fopen($fileName . '_' . $i . '.csv', 'w'); //生成临时文件
            fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));// 转码 防止乱码(比如微信昵称)
            // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限
            $fileNameArr[] = $fileName . '_' . $i . '.csv'; // 将数据通过fputcsv写到文件句柄
            fputcsv($fp, $xlsTitle);
            $start = $i * $limit;
            $dataArr = $this->getExportList($param,$start, $limit,false);

            foreach ($dataArr as $a) {
                $cnt++;
                if ($limit == $cnt) {
                    //刷新一下输出buffer，防止由于数据过多造成问题
                    ob_flush();
                    flush();
                    $cnt = 0;
                }
                fputcsv($fp, $a);
            }
            fclose($fp);  //每生成一个文件关闭
        }

        //进行多个文件压缩
        $zip = new \ZipArchive();
        $filename = $fileName . ".zip";
        $zip->open($filename, $zip::CREATE);   //打开压缩包
        foreach ($fileNameArr as $file) {
            $zip->addFile($file, basename($file));   //向压缩包中添加文件
        }
        $zip->close();  //关闭压缩包
        foreach ($fileNameArr as $file) {
            unlink($file); //删除csv临时文件
        }

        //输出压缩文件提供下载
        header("Cache-Control: max-age=0");
        header("Content-Description: File Transfer");
        header('Content-disposition: attachment; filename=' . basename($filename)); // 文件名
        header("Content-Type: application/zip"); // zip格式的
        header("Content-Transfer-Encoding: binary"); //
        header('Content-Length: ' . filesize($filename)); //
        @readfile($filename);//输出文件;
        unlink($filename); //删除压缩包临时文件

    }



    /**
     * 打印全部订单列表
     * @param string $dataType
     * @param array $query
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function getExportList($param = [],$start, $limit,$count = false)
    {

        $wxapp_id = self::$wxapp_id;
        $filter = $this->getDataType($param['dataType']);

        //普通订单
        $commonwhere = " common_order.is_delete=0  AND common_order.wxapp_id = {$wxapp_id}";
        $commonwhere .= $filter['commonfilter'];

        //爆品订单
        $giftswhere = " gifts_order.is_delete=0  AND gifts_order.wxapp_id ={$wxapp_id} ";
        $giftswhere .= $filter['giftsfilter'];


        if (isset($query['search']) && !empty($query['search'])) {
            $commonwhere .= " AND (common_order.order_no LIKE '%" . $query['search'] . "%' OR user1.nickName LIKE '%" . $query['search'] . "%')";
            $giftswhere .= "  AND (gifts_order.order_no LIKE '%" . $query['search'] . "%' OR user2.nickName LIKE '%" . $query['search'] . "%')";

        }
        //付款状态  (10未付款 20已付款)
        if (isset($query['pay_status']) && $query['pay_status'] > 0) {
            $commonwhere .= " AND common_order.pay_status = {$query['pay_status']}";
            $giftswhere .= "  AND gifts_order.pay_status = {$query['pay_status']}";
        }
        //下单开始时间
        if (isset($query['starttime']) && !empty($query['starttime'])) {
            $commonwhere .= " AND common_order.create_time >=" .strtotime($query['starttime']);
            $giftswhere .= "  AND gifts_order.create_time >=" .strtotime($query['starttime']);
        }

        //下单结束时间
        if (isset($query['endtime']) && !empty($query['endtime'])) {

            $endtime = strtotime($query['starttime'])+86400;

            $commonwhere .= " AND common_order.create_time <=" .$endtime;
            $giftswhere .= "  AND gifts_order.create_time <=" .$endtime;
        }

        //订单来源 (5爆品订单 10商品订单 20砍价订单 30秒杀订单 40储值卡 50当面付)
        if (isset($query['order_source']) && !empty($query['order_source'])) {
            $commonwhere .= " AND common_order.order_source = {$query['order_source']}";
            $giftswhere .= "  AND gifts_order.order_source = {$query['order_source']}";
        }

        // 用户id
        if (isset($query['user_id']) && $query['user_id'] > 0) {
            $commonwhere .= " AND user1.user_id = {$query['user_id']}";
            $giftswhere .= "  AND user2.user_id = {$query['user_id']}";
        }


        //获取订单列表
        $db = db();

        if($count==true){
            $countSql = "
        (SELECT `order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`common_order`.`is_fictitious`,`user1`.`user_id`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,`gifts_order`.`order_source`,`gifts_order`.`create_time`,10 as `order_status`,1 as `is_fictitious`,`user2`.`user_id`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time`
        ";
            //总记录
            $count = count($db->query($countSql));
            return $count;
        }



        $sql = "
        (SELECT `common_order`.`order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`user1`.`user_id`,`common_order`.`is_fictitious`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,5 as `order_source`,`gifts_order`.`create_time`,10 as `order_status`,`user2`.`user_id`,1 as `is_fictitious`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time` DESC LIMIT {$start},{$limit}
        ";
        $listData = $db->query($sql);

        $list = $this->handleOrder($listData);



        // 表格内容
        $dataArray = [];
        foreach ($list as $order) {

            switch ($order['order_source']){
                case "10"://普通订单
                    $order_source = "普通订单";
                    break;
                case "20"://砍价订单
                    $order_source = "砍价订单";
                    break;
                case "30"://秒杀订单
                    $order_source = "秒杀订单";
                    break;
                case "40"://储值卡订单
                    $order_source = "储值卡订单";
                    break;
                case "50"://当面付
                    $order_source = "当面付";
                    break;
                case "5"://爆品礼订单
                    $order_source = "爆品礼订单";
                    break;

            }

            if($order['pay_status']==10){
                $pay_status = "待付款";
            }elseif($order['pay_status']==20){
                $pay_status = "已付款";
            }

            if($order['pay_type']==10){
                $pay_type = "余额支付";
            }elseif($order['pay_type']==20){
                $pay_type = "微信支付";
            }

            $goodsInfo = $this->filterGoodsInfo($order);

            $dataArray[] = [
                '订单号' => $this->filterValue($order['order_no']),
                '商品信息' => $goodsInfo,
                '买家' => $this->filterValue($order['nickName']),
                '实付款' => $this->filterValue($order['pay_price']),
                '付款状态' => $this->filterValue($pay_status),
                '支付方式' => $this->filterValue($pay_type),
                '订单类型' => $this->filterValue($order_source),
                '下单时间' => $this->filterValue($order['create_time']),
            ];
        }

        return  $dataArray;

    }



    /**
     * 格式化商品信息
     * @param $order
     * @return string
     */
    private function filterGoodsInfo($order)
    {

        $content = '';
        foreach ($order['goods'] as $key => $goods) {
            $content .= ($key + 1) . ".商品名称：{$goods['goods_name']}\n";
            $content .= "　购买数量：{$goods['total_num']}\n";
            $content .= "　商品单价：{$goods['goods_price']}元\n\n";
        }
        return $content;
    }

    /**
     * 表格值过滤
     * @param $value
     * @return string
     */
    private function filterValue($value)
    {
        return "\t" . $value . "\t";
    }


    /**
     * 日期值过滤
     * @param $value
     * @return string
     */
    private function filterTime($value)
    {

        if (!$value) return '';
        return $this->filterValue(date('Y-m-d H:i:s', $value));
    }


    /**
     * 确认发货(单独订单)
     * @param $data
     * @return array|bool|false
     * @throws \app\common\exception\BaseException
     * @throws \think\Exception
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    public function delivery($data)
    {
        // 转义为订单列表
        $orderList = [$this];

        // 验证订单是否满足发货条件
        if (!$this->verifyDelivery($orderList)) {
            return false;
        }
        // 整理更新的数据
        $updateList = [[
            'order_id' => $this['order_id'],
            'express_id' => $data['express_id'],
            'express_no' => $data['express_no']
        ]];
        // 更新订单发货状态
        if ($status = $this->updateToDelivery($updateList)) {
            // 获取已发货的订单
            $completed = self::detail($this['order_id'], ['user', 'address', 'goods', 'express']);
            // 发送消息通知
            //$this->sendDeliveryMessage([$completed]);
            // 同步好物圈订单
            //(new WowService($this['wxapp_id']))->update([$completed]);
        }
        return $status;
    }


    /**
     * 验证订单是否满足发货条件
     * @param $orderList
     * @return bool
     */
    private function verifyDelivery($orderList)
    {
        foreach ($orderList as $order) {
            if (
                $order['pay_status']['value'] != 20
                || $order['delivery_type']['value'] != DeliveryTypeEnum::EXPRESS
                || $order['delivery_status']['value'] != 10
            ) {
                $this->error = "订单号[{$order['order_no']}] 不满足发货条件!";
                return false;
            }
        }
        return true;
    }

    /**
     * 更新订单发货状态(批量)
     * @param $orderList
     * @return array|false
     * @throws \Exception
     */
    private function updateToDelivery($orderList)
    {
        $data = [];
        foreach ($orderList as $item) {
            $data[] = [
                'order_id' => $item['order_id'],
                'express_no' => $item['express_no'],
                'express_id' => $item['express_id'],
                'delivery_status' => 20,
                'delivery_time' => time(),
            ];
        }
        return $this->isUpdate()->saveAll($data);
    }


    /**
     * 批量发货
     * @param $data
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    public function batchDelivery($data)
    {
        // 获取csv文件中的数据
        if (!$csvData = $this->getCsvData()) {
            return false;
        }
        // 整理订单id集
        $orderNos = helper::getArrayColumn($csvData, 0);
        // 获取订单列表数据
        $orderList = helper::arrayColumn2Key($this->getListByOrderNos($orderNos), 'order_no');
        // 验证订单是否存在
        $tempArr = array_values(array_diff($orderNos, array_keys($orderList)));
        if (!empty($tempArr)) {
            $this->error = "订单号[{$tempArr[0]}] 不存在!";
            return false;
        }
        // 整理物流单号
        $updateList = [];
        foreach ($csvData as $item) {
            $updateList[] = [
                'order_id' => $orderList[$item[0]]['order_id'],
                'express_id' => $data['express_id'],
                'express_no' => $item[1],
            ];
        }
        // 验证订单是否满足发货条件
        if (!$this->verifyDelivery($orderList)) {
            return false;
        }
        // 更新订单发货状态(批量)
        if ($status = $this->updateToDelivery($updateList)) {
            // 获取已发货的订单
            $completed = $this->getListByOrderNos($orderNos, ['user', 'address', 'goods', 'express']);
            // 发送消息通知
            //$this->sendDeliveryMessage($completed);
            //  同步好物圈订单
            //(new WowService(self::$wxapp_id))->update($completed);
        }
        return $status;
    }

    /**
     * 获取csv文件中的数据
     * @return array|bool
     */
    private function getCsvData()
    {
        // 获取表单上传文件 例如上传了001.jpg
        $file = \request()->file('iFile');
        if (empty($file)) {
            $this->error = '请上传发货模板';
            return false;
        }
        // 设置区域信息
        setlocale(LC_ALL, 'zh_CN');
        // 打开上传的文件
        $csvFile = fopen($file->getInfo()['tmp_name'], 'r');
        // 忽略第一行(csv标题)
        fgetcsv($csvFile);
        // 遍历并记录订单信息
        $orderList = [];
        while ($item = fgetcsv($csvFile)) {
            if (!isset($item[0]) || empty($item[0]) || !isset($item[1]) || empty($item[1])) {
                $this->error = '模板文件数据不合法';
                return false;
            }
            $orderList[] = $item;
        }
        if (empty($orderList)) {
            $this->error = '模板文件中没有订单数据';
            return false;
        }
        return $orderList;
    }


    /**
     * 审核：用户取消订单
     * @param $data
     * @return bool|mixed
     * @throws \app\common\exception\BaseException
     * @throws \think\exception\DbException
     */
    public function confirmCancel($data)
    {
        // 判断订单是否有效
        if ($this['pay_status']['value'] != 20) {
            $this->error = '该订单不合法';
            return false;
        }

        // 判断订单是否有效
        if ($this['order_status']['value'] != 21) {
            $this->error = '该订单不合法';
            return false;
        }

        // 订单取消事件
        $status = $this->transaction(function () use ($data) {
            if ($data['is_cancel'] == true) {
                // 执行退款操作
                (new RefundService)->execute($this);
                // 回退商品库存
                FactoryStock::getFactory($this['order_source'])->backGoodsStock($this['goods'], true);
                // 回退用户优惠券
                $this['coupon_id'] > 0 && UserCouponModel::setIsUse($this['coupon_id'], false);
                // 回退用户积分
                $User = UserModel::detail($this['user_id']);
                $describe = "订单取消：{$this['order_no']}";
                $this['points_num'] > 0 && $User->setIncPoints($this['points_num'], $describe);
                // 回退用户零钱
                $this['balance_num'] > 0 && $User->setIncBalance($this['balance_num'], $describe,40);
            }
            // 更新订单状态
            return $this->save(['order_status' => $data['is_cancel'] ? 20 : 10]);
        });
//        if ($status == true) {
//            // 同步好物圈订单
//            (new WowService(self::$wxapp_id))->update([$this]);
//        }
        return $status;
    }


    /**
     * 所有订单列表
     * @param string $dataType
     * @param array $query
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function getAllList($query = [])
    {

        $wxapp_id = self::$wxapp_id;

        //普通订单
        $commonwhere = " common_order.is_delete=0 AND common_order.pay_status=20 AND  common_order.wxapp_id ={$wxapp_id}";

        //爆品订单
        $giftswhere = " gifts_order.is_delete=0 AND gifts_order.pay_status=20 AND  gifts_order.wxapp_id ={$wxapp_id}";


        if (isset($query['search']) && !empty($query['search'])) {
            $commonwhere .= " AND (common_order.order_no LIKE '%" . $query['search'] . "%' OR user1.nickName LIKE '%" . $query['search'] . "%')";
            $giftswhere .= "  AND (gifts_order.order_no LIKE '%" . $query['search'] . "%' OR user2.nickName LIKE '%" . $query['search'] . "%')";

        }

        //下单开始时间
        if (isset($query['starttime']) && !empty($query['starttime'])) {
            $commonwhere .= " AND common_order.create_time >=" .strtotime($query['starttime']);
            $giftswhere .= "  AND gifts_order.create_time >=" .strtotime($query['starttime']);
        }

        //下单结束时间
        if (isset($query['endtime']) && !empty($query['endtime'])) {

            $endtime = strtotime($query['starttime'])+86400;

            $commonwhere .= " AND common_order.create_time <=" .$endtime;
            $giftswhere .= "  AND gifts_order.create_time <=" .$endtime;
        }

        //订单来源 (5爆品订单 10商品订单 20砍价订单 30秒杀订单 40储值卡 50当面付)
        if (isset($query['order_source']) && !empty($query['order_source'])) {
            $commonwhere .= " AND common_order.order_source = {$query['order_source']}";
            $giftswhere .= "  AND gifts_order.order_source = {$query['order_source']}";
        }

        // 用户id
        if (isset($query['user_id']) && $query['user_id'] > 0) {
            $commonwhere .= " AND user1.user_id = {$query['user_id']}";
            $giftswhere .= "  AND user2.user_id = {$query['user_id']}";
        }


        $page = isset($query['page']) && is_numeric($query['page']) ? intval($query['page']) : 1;
        $limit = 15;
        $offset = ($page - 1) * $limit;

        //获取订单列表
        $db = db();

        $countSql = "
        (SELECT `order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`common_order`.`coupon_money`,`common_order`.`balance_money`,`common_order`.`is_fictitious`,`user1`.`user_id`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,`gifts_order`.`order_source`,`gifts_order`.`create_time`,10 as `order_status`,0 as `coupon_money`,0 as `balance_money`,1 as `is_fictitious`,`user2`.`user_id`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time`
        ";
        //总记录
        $count = count($db->query($countSql));

        $sql = "
        (SELECT `common_order`.`order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`common_order`.`coupon_money`,`common_order`.`balance_money`,`user1`.`user_id`,`common_order`.`is_fictitious`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,5 as `order_source`,`gifts_order`.`create_time`,10 as `order_status`,0 as `coupon_money`,0 as `balance_money`,`user2`.`user_id`,1 as `is_fictitious`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time` DESC LIMIT {$offset},{$limit}
        ";
        $listData = $db->query($sql);

        $list = $this->handleOrder($listData);

        //计算总页数
        $last_page = 0;

        $last_page = ceil( $count/15);

        $data = [
            'total' => $count,//总条数
            'per_page' => 15,//每页的条数
            'last_page' => $last_page,//总共多少页
            'data' => $list,//数据
        ];

        return $data;

    }




    /**
     * 全部订单导出
     * @param $dataType
     * @param $query
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function orderExport($query)
    {


        header("Content-type:text/html;charset=utf-8");
        $mpName = '订单';
        $limit = 500;//每次只从数据库取50000条以防变量缓存太大
        // buffer计数器
        $cnt = 0;
        set_time_limit(0);
        //计算总的数据
        $sqlCount = $this->getFinanceExportList($query,0, $limit,true);

        if($sqlCount<1){
            $this->error = '无数据导出';
            return false;
        }

        $xlsTitle = [
            '订单号', '商品信息', '买家', '实付款', '支付状态', '支付方式', '订单类型','下单时间'
        ];

        $fileName = $mpName . date('Y-m-d');// 文件名称可根据自己情况设定
        // 输出Excel文件头，可把user.csv换成你要的文件名
        header('Content-Type: application/vnd.ms-excel;charset=utf-8');
        header('Content-Disposition: attachment;filename="' . $fileName . '"');
        header('Cache-Control: max-age=0');


        $fileNameArr = array();
        // 逐行取出数据，不浪费内存
        for ($i = 0; $i < ceil($sqlCount / $limit); $i++) {

            $fp = fopen($fileName . '_' . $i . '.csv', 'w'); //生成临时文件
            fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));// 转码 防止乱码(比如微信昵称)
            // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限
            $fileNameArr[] = $fileName . '_' . $i . '.csv'; // 将数据通过fputcsv写到文件句柄
            fputcsv($fp, $xlsTitle);
            $start = $i * $limit;
            $dataArr = $this->getFinanceExportList($query,$start, $limit,false);

            foreach ($dataArr as $a) {
                $cnt++;
                if ($limit == $cnt) {
                    //刷新一下输出buffer，防止由于数据过多造成问题
                    ob_flush();
                    flush();
                    $cnt = 0;
                }
                fputcsv($fp, $a);
            }
            fclose($fp);  //每生成一个文件关闭
        }

        //进行多个文件压缩
        $zip = new \ZipArchive();
        $filename = $fileName . ".zip";
        $zip->open($filename, $zip::CREATE);   //打开压缩包
        foreach ($fileNameArr as $file) {
            $zip->addFile($file, basename($file));   //向压缩包中添加文件
        }
        $zip->close();  //关闭压缩包
        foreach ($fileNameArr as $file) {
            unlink($file); //删除csv临时文件
        }

        //输出压缩文件提供下载
        header("Cache-Control: max-age=0");
        header("Content-Description: File Transfer");
        header('Content-disposition: attachment; filename=' . basename($filename)); // 文件名
        header("Content-Type: application/zip"); // zip格式的
        header("Content-Transfer-Encoding: binary"); //
        header('Content-Length: ' . filesize($filename)); //
        @readfile($filename);//输出文件;
        unlink($filename); //删除压缩包临时文件

    }


    /**
     * 打印全部订单列表
     * @param string $dataType
     * @param array $query
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function getFinanceExportList($query = [],$start, $limit,$count = false)
    {

        $wxapp_id = self::$wxapp_id;

        //普通订单
        $commonwhere = " common_order.is_delete=0  AND common_order.wxapp_id = {$wxapp_id} AND common_order.pay_status=20";

        //爆品订单
        $giftswhere = " gifts_order.is_delete=0  AND gifts_order.wxapp_id ={$wxapp_id} AND gifts_order.pay_status=20";


        if (isset($query['search']) && !empty($query['search'])) {
            $commonwhere .= " AND (common_order.order_no LIKE '%" . $query['search'] . "%' OR user1.nickName LIKE '%" . $query['search'] . "%')";
            $giftswhere .= "  AND (gifts_order.order_no LIKE '%" . $query['search'] . "%' OR user2.nickName LIKE '%" . $query['search'] . "%')";

        }
        //付款状态  (10未付款 20已付款)
        if (isset($query['pay_status']) && $query['pay_status'] > 0) {
            $commonwhere .= " AND common_order.pay_status = {$query['pay_status']}";
            $giftswhere .= "  AND gifts_order.pay_status = {$query['pay_status']}";
        }
        //下单开始时间
        if (isset($query['starttime']) && !empty($query['starttime'])) {
            $commonwhere .= " AND common_order.create_time >=" .strtotime($query['starttime']);
            $giftswhere .= "  AND gifts_order.create_time >=" .strtotime($query['starttime']);
        }

        //下单结束时间
        if (isset($query['endtime']) && !empty($query['endtime'])) {

            $endtime = strtotime($query['starttime'])+86400;

            $commonwhere .= " AND common_order.create_time <=" .$endtime;
            $giftswhere .= "  AND gifts_order.create_time <=" .$endtime;
        }

        //订单来源 (5爆品订单 10商品订单 20砍价订单 30秒杀订单 40储值卡 50当面付)
        if (isset($query['order_source']) && !empty($query['order_source'])) {
            $commonwhere .= " AND common_order.order_source = {$query['order_source']}";
            $giftswhere .= "  AND gifts_order.order_source = {$query['order_source']}";
        }

        // 用户id
        if (isset($query['user_id']) && $query['user_id'] > 0) {
            $commonwhere .= " AND user1.user_id = {$query['user_id']}";
            $giftswhere .= "  AND user2.user_id = {$query['user_id']}";
        }


        //获取订单列表
        $db = db();

        if($count==true){
            $countSql = "
        (SELECT `order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`common_order`.`is_fictitious`,`user1`.`user_id`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,`gifts_order`.`order_source`,`gifts_order`.`create_time`,10 as `order_status`,1 as `is_fictitious`,`user2`.`user_id`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time`
        ";
            //总记录
            $count = count($db->query($countSql));
            return $count;
        }



        $sql = "
        (SELECT `common_order`.`order_id`,`common_order`.`order_no`,`common_order`.`pay_price`,`common_order`.`pay_time`,`common_order`.`pay_status`,`common_order`.`pay_type` ,`order_source`,`common_order`.`create_time`,`common_order`.`order_status`,`user1`.`user_id`,`common_order`.`is_fictitious`,`user1`.`nickName`
        FROM `yoshop_order` `common_order`
        LEFT JOIN `yoshop_user` `user1` ON `common_order`.`user_id`=`user1`.`user_id`
        WHERE {$commonwhere})
        UNION
        (SELECT `gifts_order`.`order_id`,`gifts_order`.`order_no`,`gifts_order`.`pay_price`,`gifts_order`.`pay_time`,`gifts_order`.`pay_status`,`gifts_order`.`pay_type` ,5 as `order_source`,`gifts_order`.`create_time`,10 as `order_status`,`user2`.`user_id`,1 as `is_fictitious`,`user2`.`nickName`
        FROM `yoshop_gifts_order` `gifts_order`
        LEFT JOIN `yoshop_user` `user2` ON `gifts_order`.`user_id`=`user2`.`user_id`
        WHERE {$giftswhere}) 
        ORDER BY `create_time` DESC LIMIT {$start},{$limit}
        ";
        $listData = $db->query($sql);

        $list = $this->handleOrder($listData);



        // 表格内容
        $dataArray = [];
        foreach ($list as $order) {

            switch ($order['order_source']){
                case "10"://普通订单
                    $order_source = "普通订单";
                    break;
                case "20"://砍价订单
                    $order_source = "砍价订单";
                    break;
                case "30"://秒杀订单
                    $order_source = "秒杀订单";
                    break;
                case "40"://储值卡订单
                    $order_source = "储值卡订单";
                    break;
                case "50"://当面付
                    $order_source = "当面付";
                    break;
                case "5"://爆品礼订单
                    $order_source = "爆品礼订单";
                    break;

            }

            if($order['pay_status']==10){
                $pay_status = "待付款";
            }elseif($order['pay_status']==20){
                $pay_status = "已付款";
            }

            if($order['pay_type']==10){
                $pay_type = "余额支付";
            }elseif($order['pay_type']==20){
                $pay_type = "微信支付";
            }

            $goodsInfo = $this->filterGoodsInfo($order);

            $dataArray[] = [
                '订单号' => $this->filterValue($order['order_no']),
                '商品信息' => $goodsInfo,
                '买家' => $this->filterValue($order['nickName']),
                '实付款' => $this->filterValue($order['pay_price']),
                '付款状态' => $this->filterValue($pay_status),
                '支付方式' => $this->filterValue($pay_type),
                '订单类型' => $this->filterValue($order_source),
                '下单时间' => $this->filterValue($order['create_time']),
            ];
        }

        return  $dataArray;

    }



    /**
     * 储值卡充值订单列表
     * @param string $dataType
     * @param array $query
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function cardOrder($query = [])
    {
        // 检索查询条件
        !empty($query) && $this->setWhere($query);
        // 获取数据列表
        return $this->with(['orderplan', 'user'])
            ->alias('order')
            ->field('order.*')
            ->join('user', 'user.user_id = order.user_id')
            ->where(['order.order_source'=>40])
            ->where('order.is_delete', '=', 0)
            ->order(['order.create_time' => 'desc'])
            ->paginate(15, false, [
                'query' => \request()->request()
            ]);

    }


    /**
     * 设置检索查询条件
     * @param $query
     */
    private function setWhere($query)
    {
        if (isset($query['search']) && !empty($query['search'])) {
            $this->where('order_no|user.nickName', 'like', '%' . trim($query['search']) . '%');
        }
        if (isset($query['start_time']) && !empty($query['start_time'])) {
            $this->where('order.create_time', '>=', strtotime($query['start_time']));
        }
        if (isset($query['end_time']) && !empty($query['end_time'])) {
            $this->where('order.create_time', '<', strtotime($query['end_time']) + 86400);
        }
        // 订单状态
        if (isset($query['pay_status']) && $query['pay_status'] > 0) {
            $this->where('order.pay_status', '=', (int)$query['pay_status']);
        }

    }




    /**
     * 营销管理储值卡订单导出
     * @param $dataType
     * @param $query
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function exportCardList($query)
    {
        header("Content-type:text/html;charset=utf-8");
        $mpName = '储值卡订单';
        $limit = 500;//每次只从数据库取50000条以防变量缓存太大
        // buffer计数器
        $cnt = 0;
        set_time_limit(0);
        //计算总的数据
        $sqlCount = $this->gettCardListAll($query,0, $limit,true);
        if($sqlCount<1){
            $this->error = '无数据导出';
            return false;
        }
        $xlsTitle = [
            '订单编号', '储值卡', '订单金额', '赠送积分', '下单人', '交易状态', '下单时间'
        ];

        $fileName = $mpName . date('Y-m-d');// 文件名称可根据自己情况设定
        // 输出Excel文件头，可把user.csv换成你要的文件名
        header('Content-Type: application/vnd.ms-excel;charset=utf-8');
        header('Content-Disposition: attachment;filename="' . $fileName . '"');
        header('Cache-Control: max-age=0');



        $fileNameArr = array();
        // 逐行取出数据，不浪费内存
        for ($i = 0; $i < ceil($sqlCount / $limit); $i++) {

            $fp = fopen($fileName . '_' . $i . '.csv', 'w'); //生成临时文件
            fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));// 转码 防止乱码(比如微信昵称)
            // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限
            $fileNameArr[] = $fileName . '_' . $i . '.csv'; // 将数据通过fputcsv写到文件句柄
            fputcsv($fp, $xlsTitle);
            $start = $i * $limit;
            $dataArr = $this->gettCardListAll($query, $start, $limit,false);

            foreach ($dataArr as $a) {
                $cnt++;
                if ($limit == $cnt) {
                    //刷新一下输出buffer，防止由于数据过多造成问题
                    ob_flush();
                    flush();
                    $cnt = 0;
                }
                fputcsv($fp, $a);
            }
            fclose($fp);  //每生成一个文件关闭
        }

        //进行多个文件压缩
        $zip = new \ZipArchive();
        $filename = $fileName . ".zip";
        $zip->open($filename, $zip::CREATE);   //打开压缩包
        foreach ($fileNameArr as $file) {
            $zip->addFile($file, basename($file));   //向压缩包中添加文件
        }
        $zip->close();  //关闭压缩包
        foreach ($fileNameArr as $file) {
            unlink($file); //删除csv临时文件
        }

        //输出压缩文件提供下载
        header("Cache-Control: max-age=0");
        header("Content-Description: File Transfer");
        header('Content-disposition: attachment; filename=' . basename($filename)); // 文件名
        header("Content-Type: application/zip"); // zip格式的
        header("Content-Transfer-Encoding: binary"); //
        header('Content-Length: ' . filesize($filename)); //
        @readfile($filename);//输出文件;
        unlink($filename); //删除压缩包临时文件


    }


    /**
     * 营销管理储值卡订单导出
     * @param $dataType
     * @param array $query
     * @return false|\PDOStatement|string|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function gettCardListAll($query = [],$start, $limit,$count = false)
    {
        // 检索查询条件
        !empty($query) && $this->setWhere($query);

        if($count==true){
            // 获取数据列表
            return $this->with(['orderplan', 'user'])
                ->alias('order')
                ->field('order.*')
                ->join('user', 'user.user_id = order.user_id')
                ->where(['order.order_source'=>40])
                ->where('order.is_delete', '=', 0)
                ->order(['order.create_time' => 'desc'])
                ->count();
        }

        // 获取数据列表
        $list =  $this->with(['orderplan', 'user'])
            ->alias('order')
            ->field('order.*')
            ->join('user', 'user.user_id = order.user_id')
            ->where(['order.order_source'=>40])
            ->where('order.is_delete', '=', 0)
            ->order(['order.create_time' => 'desc'])
            ->limit($start,$limit)
            ->select();

        // 表格内容
        $dataArray = [];
        foreach ($list as $order) {
            $dataArray[] = [
                '订单编号' => $this->filterValue($order['order_no']),
                '储值卡' => $this->filterValue($order['orderplan']['card_title']),
                '订单金额' => $this->filterValue($order['pay_price']),
                '赠送积分' => $this->filterValue($order['orderplan']['reward_percent']),
                '下单人' => $this->filterValue($order['user']['nickName']),
                '交易状态' => $this->filterValue($order['pay_status']['text']),
                '下单时间' => $this->filterValue($order['create_time']),
            ];
        }

        return $dataArray;
    }


}
